package com.ldn.starter.aspect;

import cn.hutool.json.JSONUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import java.util.Optional;

/**
 * @author 李大牛家的牛 (scafel@163.com)
 * @createDate 2024/7/9 - 17:01
 * @description SPRING请求的监控
 **/
@Slf4j
@Aspect
@Component
public class RequestAspect {

    @Pointcut(
            "@annotation(org.springframework.web.bind.annotation.PostMapping)" +
                    "|| @annotation(org.springframework.web.bind.annotation.GetMapping)" +
                    "|| @annotation(org.springframework.web.bind.annotation.PutMapping)" +
                    "|| @annotation(org.springframework.web.bind.annotation.DeleteMapping)" +
                    "|| @annotation(org.springframework.web.bind.annotation.PatchMapping)"
    )
    private void webLog() {}

    @Around("webLog()")
    public Object after(ProceedingJoinPoint joinPoint) throws Throwable{
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert requestAttributes != null;
        HttpServletRequest request = requestAttributes.getRequest();
        StringBuilder s = new StringBuilder();
        s.append("【请求日志】\n");
        s.append("after 请求日志的打印\n");
        s.append("after 请求地址:").append(Optional.of(request.getRequestURI()).orElse(null)).append("\n");
        s.append("after 请求方式:").append(request.getMethod()).append("\n");
        s.append("after 请求类方法:").append(joinPoint.getSignature()).append("\n");
        s.append("after 请求参数:").append(getParams(joinPoint)).append("\n");
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long end = System.currentTimeMillis();
        s.append("after 执行返回结果:").append(JSONUtil.toJsonStr(result)).append("\n");
        s.append("after 执行耗时:").append(end - start).append("\n");
        log.info(s.toString());
        return result;
    }

    private String getParams(JoinPoint joinPoint) {
        StringBuilder params = new StringBuilder();
        if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) {
            for (int i = 0; i < joinPoint.getArgs().length; i++) {
                Object arg = joinPoint.getArgs()[i];
                if ((arg instanceof HttpServletResponse) || (arg instanceof HttpServletRequest)
                        || (arg instanceof MultipartFile) || (arg instanceof MultipartFile[])) {
                    continue;
                }
                if (arg == null) {
                    continue;
                }
                try {
                    params.append(arg).append(",");
                } catch (Exception e1) {
                    log.error("getParams 获取参数失败! =>{}", e1.getMessage());
                }
            }
        }
        return params.toString();
    }
}
